import numpy as np
import pylab

np.seterr(invalid='ignore')

d0=0.5  #两须之间的初始距离
d00=1e-5   #两须之间的最小距离
x0=10  
y0=10   #初始坐标值
step=1  #初始步长大小
step0=0.00001   #步长大小的最小距离

#目标函数
def f(X): 
    return np.exp(2*X[0])+(X[1]-np.log(X[0]+X[1]))**2
    #print(f(0,1))  实际最小值解：x=0  y=1

    
def BAS(x0,y0,d0,step):
    minvalue=10000000   #用于存最小值
    oldminvalue=minvalue
    dir=np.array([np.random.random(),np.random.random()])   #随机生成天牛移动的方向矩阵
    dir=dir/np.linalg.norm(dir,ord=2) # 归一化
    x=np.array([x0,y0])
    xl=x+d0*dir/2
    xr=x-d0*dir/2
    fl=f(xl)
    fr=f(xr)
    if minvalue>fr:minvalue=fr
    if minvalue>fl:minvalue=fl
    k=0
    while True:
        k+=1
        oldminvalue=minvalue
        x=x-step*dir*np.sign(fl-fr)
        if x[0]+x[1]>1e-10:   
            dir=np.array([np.random.random(),np.random.random()])  #随机生成天牛移动的方向矩阵
            dir=dir/np.linalg.norm(dir,ord=2) # 归一化
            xl=x+d0*dir/2   #左须坐标
            xr=x-d0*dir/2   #右须坐标
            fl=f(xl)  #左须函数值
            fr=f(xr)  #右须函数值
            minvalue=(fl+fr)/2
            step=step*0.96+step0   #变步长
            d0=d0*0.96+d00   #变须长
            if abs(oldminvalue-minvalue)<1e-6:   #收敛条件判断
                break
    print('最终迭代步数：',k)
    return x
    
x=BAS(x0,y0,d0,step)
print('该函数的最小值点坐标为：',x,'最小值为：',f(x))


##计算结果：
##最终迭代步数： 150
##该函数的最小值点坐标为： [-0.00264302  1.00182618] 最小值为： 2.0000216014314294